// Copyright (C) 1953-2022 NUDT
// Verilog module name - opensync_protocol_parse
// Version: V4.1.0.20221206
// Created:
//         by - fenglin
////////////////////////////////////////////////////////////////////////////
// Description:
//         
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module opensync_protocol_parse
(
    i_clk,
    i_rst_n,
    
    iv_data,
	i_data_wr,

	ov_data_mrq,
	o_data_wr_mrq,
    
	ov_data_mrs,
	o_data_wr_mrs,
    
    ov_data_snp        ,
	o_data_wr_snp      ,
    ov_tsmp_subtype    ,
    
    ov_data_sip        ,
	o_data_wr_sip      ,

    ov_data_anp        ,
	o_data_wr_anp         
);

// I/O
// clk & rst
input                   i_clk;
input                   i_rst_n; 
// pkt input
input	   [8:0]	    iv_data;
input	         	    i_data_wr;
// pkt output to NMA
output reg [8:0]	    ov_data_mrq    ;
output reg	            o_data_wr_mrq  ;
// pkt output to osp
output reg [8:0]	    ov_data_mrs    ;
output reg	            o_data_wr_mrs  ;
// pkt output to pip
output reg [8:0]	    ov_data_snp        ;
output reg	            o_data_wr_snp      ;
output reg [7:0]	    ov_tsmp_subtype    ;
// pkt output to sip
output reg [8:0]	    ov_data_sip        ;
output reg	            o_data_wr_sip      ;
// pkt output to anp
output reg [8:0]	    ov_data_anp        ;
output reg	            o_data_wr_anp      ;
//***************************************************
//      add valid of data and delay 8 cycles
//***************************************************
reg        [134:0]      rv_data;
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n) begin
        rv_data         <= 135'b0;
    end
    else begin
        if(i_data_wr)begin
            rv_data     <= {rv_data[125:0],iv_data};
        end
        else begin
            rv_data     <= {rv_data[125:0],9'b0};
        end        
    end
end
//***************************************************
//       receive pit record in ctrl interface
//***************************************************
(*MARK_DEBUG="true"*)reg         [7:0]      rv_response_cnt;
(*MARK_DEBUG="true"*)reg         [7:0]      rv_response_follow_up_cnt;

reg       [2:0]               rv_osp_state;
localparam      IDLE_S            = 3'd0,
                TRANS_MRQ_S       = 3'd1,
                TRANS_MRS_S       = 3'd2,
                TRANS_SNP_S       = 3'd3,
                TRANS_SIP_S       = 3'd4,
                TRANS_ANP_S       = 3'd5,
                DISCARD_PKT_S     = 3'd6;
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n)begin
        ov_data_mrq    <= 9'b0;
        o_data_wr_mrq  <= 1'b0;

        ov_data_mrs    <= 9'b0;
        o_data_wr_mrs  <= 1'b0;

        ov_data_snp         <= 9'b0;
        o_data_wr_snp       <= 1'b0;
        ov_tsmp_subtype     <= 8'b0;
        
        ov_data_sip    <= 9'b0;
        o_data_wr_sip  <= 1'b0;
        
        ov_data_anp    <= 9'b0;
        o_data_wr_anp  <= 1'b0;
        
        rv_response_cnt           <= 8'b0;
        rv_response_follow_up_cnt <= 8'b0;        
        
        rv_osp_state   <= IDLE_S;        
    end
    else begin
        case(rv_osp_state)
            IDLE_S:begin
			    if(rv_data[134])begin//transmit first cycle.
                    ov_tsmp_subtype     <= iv_data[7:0];
					if(({rv_data[25:18],rv_data[16:9]} == 16'hff01) && (rv_data[7:0] == 8'h06) && ((iv_data[7:0] == 8'h03)||(iv_data[7:0] == 8'h04)))begin//pdelay_resp,pdelay_resp_follow_up.
						ov_data_mrq    <= rv_data[134:126];
						o_data_wr_mrq  <= 1'b1;

						ov_data_mrs    <= 9'b0;
						o_data_wr_mrs  <= 1'b0;

						ov_data_snp    <= 9'b0;
						o_data_wr_snp  <= 1'b0;
                        
                        ov_data_sip    <= 9'b0;
                        o_data_wr_sip  <= 1'b0;
                        
                        ov_data_anp    <= 9'b0;
                        o_data_wr_anp  <= 1'b0;                        

						rv_osp_state   <= TRANS_MRQ_S;
						
                        if(iv_data[7:0] == 8'h03)begin
                            rv_response_cnt           <= rv_response_cnt + 1'b1;
                        end
                        else begin
                            rv_response_cnt           <= rv_response_cnt;
                        end	
                        
                        if(iv_data[7:0] == 8'h04)begin
                            rv_response_follow_up_cnt           <= rv_response_follow_up_cnt + 1'b1;
                        end
                        else begin
                            rv_response_follow_up_cnt           <= rv_response_follow_up_cnt;
                        end                         					  
					end
					else if(({rv_data[25:18],rv_data[16:9]} == 16'hff01) && (rv_data[7:0] == 8'h06) && ((iv_data[7:0] == 8'h01)||(iv_data[7:0] == 8'h07)))begin//sync,follow_up
						ov_data_mrq    <= 9'b0;
						o_data_wr_mrq  <= 1'b0;

						ov_data_mrs    <= 9'b0;
						o_data_wr_mrs  <= 1'b0;

						ov_data_snp    <= rv_data[134:126];
						o_data_wr_snp  <= 1'b1;
                        
                        ov_data_sip    <= 9'b0;
                        o_data_wr_sip  <= 1'b0;
                        
                        ov_data_anp    <= 9'b0;
                        o_data_wr_anp  <= 1'b0;                          

						rv_osp_state   <= TRANS_SNP_S;  
					end
					else if(({rv_data[25:18],rv_data[16:9]} == 16'hff01) && (rv_data[7:0] == 8'h06) && (iv_data[7:0] == 8'h02))begin//PDELAY_REQ
						ov_data_mrq    <= 9'b0;
						o_data_wr_mrq  <= 1'b0;

						ov_data_mrs    <= rv_data[134:126];
						o_data_wr_mrs  <= 1'b1;

						ov_data_snp    <= 9'b0;
						o_data_wr_snp  <= 1'b0;
                        
                        ov_data_sip    <= 9'b0;
                        o_data_wr_sip  <= 1'b0;
                        
                        ov_data_anp    <= 9'b0;
                        o_data_wr_anp  <= 1'b0;                          

						rv_osp_state   <= TRANS_MRS_S;  
					end
					else if(({rv_data[25:18],rv_data[16:9]} == 16'hff01) && (rv_data[7:0] == 8'h06) && (iv_data[7:0] == 8'h08))begin//signaling
						ov_data_mrq    <= 9'b0;
						o_data_wr_mrq  <= 1'b0;

						ov_data_mrs    <= 9'b0;
						o_data_wr_mrs  <= 1'b0;

						ov_data_snp    <= 9'b0;
						o_data_wr_snp  <= 1'b0;
                        
                        ov_data_sip    <= rv_data[134:126];
                        o_data_wr_sip  <= 1'b1;
                        
                        ov_data_anp    <= 9'b0;
                        o_data_wr_anp  <= 1'b0;                          

						rv_osp_state   <= TRANS_SIP_S;  
					end
					else if(({rv_data[25:18],rv_data[16:9]} == 16'hff01) && (rv_data[7:0] == 8'h06) && (iv_data[7:0] == 8'h09))begin//announce
						ov_data_mrq    <= 9'b0;
						o_data_wr_mrq  <= 1'b0;

						ov_data_mrs    <= 9'b0;
						o_data_wr_mrs  <= 1'b0;

						ov_data_snp    <= 9'b0;
						o_data_wr_snp  <= 1'b0;
                        
                        ov_data_sip    <= 9'b0;
                        o_data_wr_sip  <= 1'b0;
                        
                        ov_data_anp    <= rv_data[134:126];
                        o_data_wr_anp  <= 1'b1;                        

						rv_osp_state   <= TRANS_ANP_S;  
					end                     
					else begin//discard pkt
						ov_data_mrq    <= 9'b0;
						o_data_wr_mrq  <= 1'b0;

						ov_data_mrs    <= 9'b0;
						o_data_wr_mrs  <= 1'b0;

						ov_data_snp         <= 9'b0;
						o_data_wr_snp       <= 1'b0;
						
						ov_data_sip    <= 9'b0;
						o_data_wr_sip  <= 1'b0;
						
						ov_data_anp    <= 9'b0;
						o_data_wr_anp  <= 1'b0;						
					
						rv_osp_state        <= DISCARD_PKT_S;  
					end                    
                end
                else begin
					ov_data_mrq    <= 9'b0;
					o_data_wr_mrq  <= 1'b0;

					ov_data_mrs    <= 9'b0;
					o_data_wr_mrs  <= 1'b0;

					ov_data_snp         <= 9'b0;
					o_data_wr_snp       <= 1'b0;
					
					ov_data_sip    <= 9'b0;
					o_data_wr_sip  <= 1'b0;
					
					ov_data_anp    <= 9'b0;
					o_data_wr_anp  <= 1'b0;		
                                        
                    rv_osp_state        <= IDLE_S;                      
                end
            end
            TRANS_MRQ_S:begin
                ov_data_mrq        <= rv_data[134:126];
                o_data_wr_mrq      <= 1'b1;              
                if(rv_data[134])begin//last cycle. 
                    rv_osp_state   <= IDLE_S;
                end
                else begin
                    rv_osp_state   <= TRANS_MRQ_S;
                end
            end
            TRANS_SNP_S:begin
                ov_data_snp        <= rv_data[134:126];
                o_data_wr_snp      <= 1'b1;              
                if(rv_data[134])begin//last cycle. 
                    rv_osp_state   <= IDLE_S;
                end
                else begin
                    rv_osp_state   <= TRANS_SNP_S;
                end
            end
            TRANS_MRS_S:begin
                ov_data_mrs        <= rv_data[134:126];
                o_data_wr_mrs      <= 1'b1;              
                if(rv_data[134])begin//last cycle. 
                    rv_osp_state   <= IDLE_S;
                end
                else begin
                    rv_osp_state   <= TRANS_MRS_S;
                end
            end
            TRANS_SIP_S:begin
                ov_data_sip        <= rv_data[134:126];
                o_data_wr_sip      <= 1'b1;              
                if(rv_data[134])begin//last cycle. 
                    rv_osp_state   <= IDLE_S;
                end
                else begin
                    rv_osp_state   <= TRANS_SIP_S;
                end
            end
            TRANS_ANP_S:begin
                ov_data_anp        <= rv_data[134:126];
                o_data_wr_anp      <= 1'b1;              
                if(rv_data[134])begin//last cycle. 
                    rv_osp_state   <= IDLE_S;
                end
                else begin
                    rv_osp_state   <= TRANS_ANP_S;
                end
            end             
            DISCARD_PKT_S:begin
				ov_data_mrq         <= 9'b0;
				o_data_wr_mrq       <= 1'b0;
									
				ov_data_mrs         <= 9'b0;
				o_data_wr_mrs       <= 1'b0;
									
				ov_data_snp         <= 9'b0;
				o_data_wr_snp       <= 1'b0;            
                if(rv_data[134])begin//last cycle. 
                    rv_osp_state   <= IDLE_S;
                end
                else begin
                    rv_osp_state   <= DISCARD_PKT_S;
                end
            end             
            default:begin
				ov_data_mrq    <= 9'b0;
				o_data_wr_mrq  <= 1'b0;

				ov_data_mrs    <= 9'b0;
				o_data_wr_mrs  <= 1'b0;

				ov_data_snp         <= 9'b0;
				o_data_wr_snp       <= 1'b0;
				
				ov_data_sip    <= 9'b0;
				o_data_wr_sip  <= 1'b0;
				
				ov_data_anp    <= 9'b0;
				o_data_wr_anp  <= 1'b0;	
					
                rv_osp_state <= IDLE_S;  
            end
        endcase
    end
end
endmodule